﻿using System;
using CPN.PJN.Silverlight.Common.ExceptionHandling.Configuration;

namespace CPN.PJN.Silverlight.Common.ExceptionHandling
{
    /// <summary>
    /// Cette classe représente le gestionnaire d'exceptions
    /// </summary>
    public sealed class ExceptionManager
    {
        #region Const

        /// <summary>
        /// Politique par défaut
        /// </summary>
        public const string DEFAULT_POLICY = "DefaultPolicy";

        #endregion

        #region Private Members

        /// <summary>
        /// Instance du gestionnaire d'Exception
        /// </summary>
        private static volatile ExceptionManager instance;

        /// <summary>
        /// Objet de synchronisation
        /// </summary>
        private static object syncRoot = new Object();


        #endregion

        #region Instance Property

        /// <summary>
        /// Propriété Instance du gestionnaire d'Exception
        /// </summary>
        public static ExceptionManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new ExceptionManager();
                    }
                }

                return instance;
            }
        }

        #endregion

        #region Private Constructor

        /// <summary>
        /// Constructeur privé
        /// </summary>
        private ExceptionManager()
        {
           
        }

        #endregion
        
        #region HandleException Methods

        /// <summary>
        /// Cette méthode permet d'exécuter la gestion d'exception 
        /// </summary>
        /// <param name="innerException">Exception récupérée</param>
        /// <returns>Vrai s'il faut retourner l'exception à la couche supérieure</returns>
        public bool HandleException(Exception innerException)
        {
            return this.HandleException(innerException, DEFAULT_POLICY, null);
        }

        /// <summary>
        /// Cette méthode permet d'exécuter la gestion de l'exception récupérée
        /// </summary>
        /// <param name="innerException">Exception récupérée</param>
        /// <param name="policyName">Nom de la politique d'exception</param>
        /// <param name="data">Données à ajouter dans les logs si besoin</param>
        /// <returns>Vrai s'il faut retourner l'exception à la couche supérieure</returns>
        public bool HandleException(Exception innerException, string policyName, params object[] data)
        {
            if (ExceptionConfigurationManager.Instance.PolicyDictionary.ContainsKey(policyName))
            {
                foreach (var item in ExceptionConfigurationManager.Instance.PolicyDictionary[policyName].ExceptionHandlerCollection)
                {
                    item.HandleException(innerException, data);
                }
                return ExceptionConfigurationManager.Instance.PolicyDictionary[policyName].NotifyRethrow;
            }
            return true;
        }

        #endregion
    }
}
